﻿using System;
using System.Linq;
using MVVMFramework.Core.Model;
using System.ComponentModel;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using MVVMFramework.Ria.Helpers;
using System.ServiceModel.DomainServices.Client;

namespace MVVMFramework.Ria.Model
{
    public class RiaDomainOperation : IDomainOperation
    {
        private OperationBase _op;

        public RiaDomainOperation(OperationBase op)
        {
            _op = op;
            this.RelayEvents();
        }

        #region Relay events

        private void RelayEvents()
        {
            _op.Completed += (s, e) => this.RaiseCompleted(e);
            (_op as INotifyPropertyChanged).PropertyChanged += (s, e) => this.RaisePropertyChanged(e);
        }

        private void RaiseCompleted(EventArgs e)
        {
            var completedEvt = this.Completed;
            if (completedEvt != null)
                completedEvt(this, e);
        }

        private void RaisePropertyChanged(PropertyChangedEventArgs e)
        {
            var propertyChanged = this.PropertyChanged;
            if (propertyChanged != null)
                propertyChanged(this, e);
        }

        #endregion

        #region IDomainOperation Members

        public bool CanCancel
        {
            get { return _op.CanCancel; }
        }

        public Exception Error
        {
            get { return _op.Error; }
        }

        public bool HasError
        {
            get { return _op.HasError; }
        }

        public bool IsCanceled
        {
            get { return _op.IsCanceled; }
        }

        public bool IsComplete
        {
            get { return _op.IsComplete; }
        }

        public bool IsErrorHandled
        {
            get { return _op.IsErrorHandled; }
        }

        public object UserState
        {
            get { return _op.UserState; }
        }

        public event EventHandler Completed;

        public void Cancel()
        {
            _op.Cancel(); ;
        }

        public void MarkErrorAsHandled()
        {
            _op.MarkErrorAsHandled();
        }

        #endregion

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }

    public class RiaLoadOperation : RiaDomainOperation, ILoadOperation
    {
        private LoadOperation _op;

        public RiaLoadOperation(LoadOperation op)
            : base(op)
        {
            _op = op;
        }

        #region ILoadOperation Members

        public IEnumerable AllEntities
        {
            get { return _op.AllEntities; }
        }

        public IEnumerable Entities
        {
            get { return _op.Entities; }
        }

        public ModelLoadBehavior LoadBehavior
        {
            get { return _op.LoadBehavior.AsModelLoadBehavior(); }
        }

        public int TotalEntityCount
        {
            get { return _op.TotalEntityCount; }
        }

        public IEnumerable<ValidationResult> ValidationErrors
        {
            get { return _op.ValidationErrors; }
        }

        #endregion
    }

    public sealed class RiaLoadOperation<T> : RiaLoadOperation, ILoadOperation<T>
        where T : Entity
    {
        private LoadOperation<T> _op;

        public RiaLoadOperation(LoadOperation<T> op)
            : base(op)
        {
            _op = op;
        }

        #region ILoadOperation<T> Members

        public new IEnumerable<T> Entities
        {
            get { return _op.Entities; }
        }

        #endregion
    }

    public sealed class RiaSubmitOperation : RiaDomainOperation, ISubmitOperation
    {
        private SubmitOperation _op;
        private IEntityChangeSet _ecs;

        public RiaSubmitOperation(SubmitOperation op)
            : base(op)
        {
            _op = op;
            _ecs = new RiaEntityChangeSet(_op.ChangeSet);
        }

        #region ISubmitOperation Members

        public IEntityChangeSet ChangeSet
        {
            get { return _ecs; }
        }

        public IEnumerable EntitiesInError
        {
            get { return _op.EntitiesInError; }
        }

        #endregion
    }

    internal class RiaEntityChangeSet : IEntityChangeSet
    {
        private EntityChangeSet _ecs;

        public RiaEntityChangeSet(EntityChangeSet ecs)
        {
            _ecs = ecs;
        }

        #region IEntityChangeSet Members

        public IEnumerable AddedEntities
        {
            get { return _ecs.AddedEntities; }
        }

        public IEnumerable ModifiedEntities
        {
            get { return _ecs.ModifiedEntities; }
        }

        public IEnumerable RemovedEntities
        {
            get { return _ecs.RemovedEntities; }
        }

        public bool IsEmpty
        {
            get { return _ecs.IsEmpty; }
        }

        #endregion
    }
}
